/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package brasilquad.beans;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Felipe Rooke
 */
public class NoQuad {

    private double latitude; //y
    private double longitude; //x
    private char featureClass;
    private String featureCode;
    private int geonameId;
    private int posicaoArq; //linha do txt onde se encontra mais informa??es do n?
    private NoQuad cimaDireita;
    private NoQuad cimaEsquerda;
    private NoQuad baixoDireita;
    private NoQuad baixoEsquerda;

    public NoQuad getBaixoDireita() {
        return baixoDireita;
    }

    public void setBaixoDireita(NoQuad baixoDireita) {
        this.baixoDireita = baixoDireita;
    }

    public NoQuad getBaixoEsquerda() {
        return baixoEsquerda;
    }

    public void setBaixoEsquerda(NoQuad baixoEsquerda) {
        this.baixoEsquerda = baixoEsquerda;
    }

    public NoQuad getCimaDireita() {
        return cimaDireita;
    }

    public void setCimaDireita(NoQuad cimaDireita) {
        this.cimaDireita = cimaDireita;
    }

    public NoQuad getCimaEsquerda() {
        return cimaEsquerda;
    }

    public void setCimaEsquerda(NoQuad cimaEsquerda) {
        this.cimaEsquerda = cimaEsquerda;
    }

    public char getFeatureClass() {
        return featureClass;
    }

    public void setFeatureClass(char featureClass) {
        this.featureClass = featureClass;
    }

    public String getFeatureCode() {
        return featureCode;
    }

    public void setFeatureCode(String featureCode) {
        this.featureCode = featureCode;
    }

    public int getGeonameId() {
        return geonameId;
    }

    public void setGeonameId(int geonameId) {
        this.geonameId = geonameId;
    }

    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(double latitude) {
        /*****************************************************************************************/
        /** Faz-se as convers?es de latitude talvez usando a classe convers?o que seria criada na utils **/
        /*****************************************************************************************/
        this.latitude = latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(double longitude) {
        /******************************************************************************************/
        /** Faz-se as convers?es de longitude talvez usando a classe convers?o que seria criada na utils **/
        /******************************************************************************************/
        this.longitude = longitude;
    }

    public int getPosicaoArq() {
        return posicaoArq;
    }

    public void setPosicaoArq(int posicaoArq) {
        this.posicaoArq = posicaoArq;
    }

    // Verifica entre os seus 4 filhos qual est? no quadrante especificado
    public NoQuad getNo(double latitude, double longitude) {
        // verifica se o cara esta no quandrante de cima
        if (this.longitude < longitude) {
            // verifica se o cara esta na direita
            if (this.latitude < latitude) {
                return this.cimaDireita;
                // sen?o ta na esquerda
            } else {
                return this.cimaEsquerda;
            }
            // se n?o est? em cima est? em baixo
        } else {
            // verifica se o cara esta na direita
            if (this.latitude < latitude) {
                return this.baixoDireita;
                // sen?o ta na esquerda
            } else {
                return this.baixoEsquerda;
            }
        }
    }

    // Verifica entre os seus 4 filhos o quadrante onde deve ser colocado o n? e coloca-o
    public void setNo(NoQuad no) {
        // verifica se o cara esta no quandrante de cima
        if (this.longitude < no.longitude) {
            // verifica se o cara esta na direita
            if (this.latitude < no.latitude) {
                this.setCimaDireita(no);
                // sen?o ta na esquerda
            } else {
                this.setCimaEsquerda(no);
            }
            // se n?o est? em cima est? em baixo
        } else {
            // verifica se o cara esta na direita
            if (this.latitude < no.latitude) {
                this.setBaixoDireita(no);
                // sen?o ta na esquerda
            } else {
                this.setBaixoEsquerda(no);
            }
        }
    }

    /*
     * @param O Parametro ? o n? a ser inserido
     * @see Esse m?todo ? o utilizado para inserir na arvore (ou subarvore)
     */
    public void inserirNo(NoQuad no) {
        inserirNo(this, no);
    }

    /*
     * @see esse m?todo foi criado para ser usado pelo m?todo inserirNo(no);
     */
    private void inserirNo(NoQuad raiz, NoQuad no) {
        //pega o lugar que era para o no estar
        NoQuad noPosicao = raiz.getNo(no.latitude, no.longitude);
        //verifica se o lugar que era para o no estar est? vazio
        if (noPosicao == null) {
            //j? que est? vazio coloca o n? l?
            raiz.setNo(no);
        } else {
            //se n?o est? vazio continua percorrendo
            inserirNo(noPosicao, no);
        }
    }

    /**
     * @param args the command line arguments
     */
//    public static void plotar(NoQuad raiz, TipoPonto tipo) {
//        if (raiz != null) {
//            if (tipo == null || raiz.featureCode.contains(tipo.toString())) {
//                System.out.println(raiz.geonameId);
//            }
//
//            plotar(raiz.baixoDireita, tipo);
//            plotar(raiz.baixoEsquerda, tipo);
//            plotar(raiz.cimaDireita, tipo);
//            plotar(raiz.cimaEsquerda, tipo);
//
//        }
//    }

    public static double getDistanciaEntreDoisPontos(NoQuad noA, NoQuad noB) {
        return Math.sqrt(Math.pow((noA.latitude - noB.latitude), 2) + Math.pow((noA.longitude - noB.longitude), 2));
    }

    public static double getDistanciaEntreDoisPontos(NoQuad noA, double x, double y) {
        return Math.sqrt(Math.pow((noA.longitude - x), 2) + Math.pow((noA.latitude - y), 2));
    }

    public static void getCidadesNoRaio(NoQuad raiz, double latitude, double longitude, double raio, List<NoQuad> cidades) {
        if (raiz != null) {
            //System.out.println(getDistanciaEntreDoisPontos(raiz, longitude, latitude));
            if (getDistanciaEntreDoisPontos(raiz, longitude, latitude) <= raio && raiz.getFeatureCode().equals("PPL")){
                cidades.add(raiz);
            }
            getCidadesNoRaio(raiz.baixoDireita, latitude, longitude, raio, cidades);
            getCidadesNoRaio(raiz.baixoEsquerda, latitude, longitude, raio, cidades);
            getCidadesNoRaio(raiz.cimaDireita, latitude, longitude, raio, cidades);
            getCidadesNoRaio(raiz.cimaEsquerda, latitude, longitude, raio, cidades);
        }
    }

    public static void getPraiasNoRaio(NoQuad raiz, double latitude, double longitude, double raio, List<NoQuad> cidades) {
        if (raiz != null) {
            //System.out.println(getDistanciaEntreDoisPontos(raiz, longitude, latitude));
            if (getDistanciaEntreDoisPontos(raiz, longitude, latitude) <= raio && (raiz.getFeatureCode().equals("BCH"))||raiz.getFeatureCode().equals("BCHS")){
                cidades.add(raiz);
            }
            getPraiasNoRaio(raiz.baixoDireita, latitude, longitude, raio, cidades);
            getPraiasNoRaio(raiz.baixoEsquerda, latitude, longitude, raio, cidades);
            getPraiasNoRaio(raiz.cimaDireita, latitude, longitude, raio, cidades);
            getPraiasNoRaio(raiz.cimaEsquerda, latitude, longitude, raio, cidades);
        }
    }

    public static void getEscolasNoRaio(NoQuad raiz, double latitude, double longitude, double raio, List<NoQuad> cidades) {
        if (raiz != null) {
            //System.out.println(getDistanciaEntreDoisPontos(raiz, longitude, latitude));
            if (getDistanciaEntreDoisPontos(raiz, longitude, latitude) <= raio && raiz.getFeatureCode().equals("SCH")){
                cidades.add(raiz);
            }
            getEscolasNoRaio(raiz.baixoDireita, latitude, longitude, raio, cidades);
            getEscolasNoRaio(raiz.baixoEsquerda, latitude, longitude, raio, cidades);
            getEscolasNoRaio(raiz.cimaDireita, latitude, longitude, raio, cidades);
            getEscolasNoRaio(raiz.cimaEsquerda, latitude, longitude, raio, cidades);
        }
    }

    public static void getAeroportosNoRaio(NoQuad raiz, double latitude, double longitude, double raio, List<NoQuad> cidades) {
        if (raiz != null) {
            //System.out.println(getDistanciaEntreDoisPontos(raiz, longitude, latitude));
            if (getDistanciaEntreDoisPontos(raiz, longitude, latitude) <= raio && raiz.getFeatureCode().equals("AIRP")){
                cidades.add(raiz);
            }
            getAeroportosNoRaio(raiz.baixoDireita, latitude, longitude, raio, cidades);
            getAeroportosNoRaio(raiz.baixoEsquerda, latitude, longitude, raio, cidades);
            getAeroportosNoRaio(raiz.cimaDireita, latitude, longitude, raio, cidades);
            getAeroportosNoRaio(raiz.cimaEsquerda, latitude, longitude, raio, cidades);
        }
    }

    public static void main2(String[] args) {
        // TODO code application logic here
        NoQuad no1 = new NoQuad();
        ManipulaArquivo Mapa = new ManipulaArquivo();
        no1.setLatitude(50);
        no1.setLongitude(50);
        no1.setGeonameId(1);
        no1.setFeatureCode("PPLA2");

        NoQuad no2 = new NoQuad();
        no2.setLatitude(60);
        no2.setLongitude(60);
        no2.setGeonameId(2);
        no2.setFeatureCode("SCH");

        NoQuad no3 = new NoQuad();
        no3.setLatitude(20);
        no3.setLongitude(20);
        no3.setGeonameId(3);
        no3.setFeatureCode("BCH");

        NoQuad no4 = new NoQuad();
        no4.setLatitude(70);
        no4.setLongitude(70);
        no4.setGeonameId(4);
        no4.setFeatureCode("BCHS");

        NoQuad no5 = new NoQuad();
        no5.setLatitude(72);
        no5.setLongitude(62);
        no5.setGeonameId(5);
        no5.setFeatureCode("RGNL");

        no1.inserirNo(no2);
        no1.inserirNo(no3);
        no1.inserirNo(no4);
        no1.inserirNo(no5);
        List<NoQuad> cidades = new ArrayList<NoQuad>();
        getCidadesNoRaio(no1, 45, 45, 10, cidades);
        

        System.out.println("oi");
//        NoQuad.plotar(no1, TipoPonto.Cidade);
        Mapa.lerArquivoMapa();


    }
}
